package com.tianruan.dc.modules.sys.user.service.impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianruan.dc.common.constant.GlobalExceptionEnum;
import com.tianruan.dc.common.encoding.Md5PasswordEncoder;
import com.tianruan.dc.common.exception.GlobalException;
import com.tianruan.dc.common.utils.IdGen;
import com.tianruan.dc.common.utils.MOfficeUtils;
import com.tianruan.dc.common.utils.PageUtils;
import com.tianruan.dc.common.utils.StringUtils;
import com.tianruan.dc.common.utils.encryption.Md5Utils;
import com.tianruan.dc.modules.sys.user.entity.db.*;
import com.tianruan.dc.modules.sys.user.entity.dto.LoginDTO;
import com.tianruan.dc.modules.sys.user.entity.dto.UserDTO;
import com.tianruan.dc.modules.sys.user.entity.vo.UserVO;
import com.tianruan.dc.modules.sys.user.mapper.UserMapper;
import com.tianruan.dc.modules.sys.user.service.IGradeService;
import com.tianruan.dc.modules.sys.user.service.IStudentGardeService;
import com.tianruan.dc.modules.sys.user.service.IUserService;
import com.tianruan.dc.modules.sys.user.utils.UserUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;


@Service("userService")
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements IUserService {


    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleServiceImpl userRoleService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private IGradeService gradeService;
    @Autowired
    private IStudentGardeService studentGardeService;


    public UserDTO getUserPermissionByNo(String username) {
        return userMapper.getUserPermissionByNo(username);
    }

    public Integer getUserPermissionByRoleAndUsername(String username, String roleName) {
        return baseMapper.getUserPermissionByRoleAndUsername(username, roleName);
    }

    public IPage<UserVO> pageUser(Page<UserVO> page,
                                  String officeId,
                                  String no,
                                  String username,
                                  String name,
                                  String phone,
                                  String email,
                                  List<String> roleIdList) {
        return userMapper.pageUser(page, officeId, no, username, name, phone, email, roleIdList);
    }

    @Override
    public IPage<UserVO> pageStudent(Page page, String officeId, String no, String name, String phone, String email) {
        page.setSearchCount(false);
        IPage<UserVO> userVOIPage = baseMapper.pageStudent(page, officeId, no, name, phone, email);
        Integer integer = baseMapper.pageStudentCount(officeId, no, name, phone, email);
        userVOIPage.setTotal(integer);
        return userVOIPage;
    }

    @Override
    public List<UserVO> searchTeacherList(UserDTO dtoEntity) {
        return baseMapper.searchTeacherList(dtoEntity);
    }

    @Override
    public PageUtils searchTeacher(UserDTO dtoEntity) {
        IPage<UserDO> page = new Page<>(dtoEntity.getCurrent(), dtoEntity.getPageSize());
        return new PageUtils(baseMapper.searchTeacher(page, dtoEntity));
    }

    @Override
    public PageUtils searchStudentByStudent(UserDTO dtoEntity) {
        IPage<UserDO> page = new Page<>(dtoEntity.getCurrent(), dtoEntity.getPageSize());
        return new PageUtils(baseMapper.searchStudentByStudent(page, dtoEntity));
    }

    @Override
    public IPage<UserVO> findExpertList(UserDTO dtoEntity) {
        IPage<UserDO> page = new Page<>(dtoEntity.getCurrent(), dtoEntity.getPageSize());
        return baseMapper.findExpertList(page, dtoEntity);
    }

    @Override
    public IPage<UserVO> findDCExpertList(UserDTO dtoEntity) {
        IPage<UserDO> page = new Page<>(dtoEntity.getCurrent(), dtoEntity.getPageSize());
        return baseMapper.findDCExpertList(page, dtoEntity);
    }

    public List<String> getUserRoleIdList() {
        UserDTO user = UserUtils.getUser();
        QueryWrapper<UserRoleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", user.getId());
        List<UserRoleDO> roleList = userRoleService.list(queryWrapper);
        List<String> roleIdList = new ArrayList<>();
        for (UserRoleDO userRole: roleList) {
            roleIdList.add(userRole.getRoleId());
        }
        return roleIdList;
    }

    public UserVO getUserRoleById(String id) {
        return userMapper.getUserRoleById(id);
    }

    @Transactional
    public UserDTO updateUser(String id, UserDTO userDTO){
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(userDTO,userDO);
        userDO.setId(id);
        userMapper.updateById(userDO);
        userRoleService.insertUserRole(id, userDTO.getRoleIds());
        return userDTO;
    }


    @Transactional
    public UserDTO insertUser(UserDTO userDTO) {
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(userDTO, userDO);
        // 设置密码，暂时以自己工号为密码
        String passoword = passwordEncoder.encode(userDO.getNo());
        userDO.setPassword(passoword);
        userMapper.insert(userDO);
        userRoleService.insertUserRole(userDO.getId(), userDTO.getRoleIds());
        return userDTO;
    }


    public String getPassword(String id) {
        return userMapper.getPassword(id);
    }

    /**
     * 判断密码是否相等
     * @param id
     * @param password
     * @return
     */
    public Boolean equalsPassword(String id, String password) {
        String pw = this.getPassword(id);
        return Md5Utils.validate(password, pw);
    }

    /**
     * 根据id修改密码
     * @param id
     * @param password
     */
    public void modifyPassword(String id, String password) {
        password = Md5Utils.entrypt(password);
        UserDO userDO = new UserDO().setPassword(password);
        userDO.setId(id);
        userMapper.updateById(userDO);
    }

    @Override
    public UserDTO getUserByPhone(String phone) {
        return baseMapper.getUserByPhone(phone);
    }

    @Override
    public List<UserDTO> getUserByRoleId(String roleId) {
        return baseMapper.getUserByRoleId(roleId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean importStudent(MultipartFile file) {

        // 获取班级
        List<GradeDO> gradeList = gradeService.list();


        Workbook workBook = MOfficeUtils.getWorkBook(file);
        Sheet sheet = workBook.getSheetAt(0);

        List<UserDO> userList = new ArrayList<>();                          // 学生列表
        List<StudentGardeDO> studentGardeList = new ArrayList<>();        // 学生班级列表
        List<UserRoleDO> userRoleList = new ArrayList<>();        // 学生班级列表

        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            try {
                String stringCellValue = row.getCell(0).getStringCellValue();
                if (StringUtils.isBlank(stringCellValue)) {
                    break;
                }
            } catch (Exception e) {
                break;
            }
            String no = row.getCell(0).getStringCellValue();                // 学号
            String name = row.getCell(1).getStringCellValue();              // 姓名
            String sex = row.getCell(2).getStringCellValue();               // 性别
            String grade = row.getCell(3).getStringCellValue();             // 班级
            String majorName = row.getCell(4).getStringCellValue();         // 专业
            String officeName = row.getCell(5).getStringCellValue();        // 学院
            String idCard = row.getCell(6).getStringCellValue();             // 身份证



            // 判断是否已经存在该用户
            QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", no);
            UserDO hasUser = baseMapper.selectOne(queryWrapper);
            if (hasUser != null) {
                // 用户已经存在，跳过
                continue;
            }


            UserDTO userDTO = new UserDTO();
            userDTO.setCompanyId("1");

            userDTO.setName(name);
            userDTO.setUsername(no);
            userDTO.setNo(no);
            // 默认密码为学号
            userDTO.setPassword(new Md5PasswordEncoder().encode(idCard.substring(idCard.length() - 6)));
            userDTO.setType("1");
            userDTO.preInsert();

            // 添加学生对应班级
            for(GradeDO gradeDO: gradeList) {
                if(gradeDO.getName().equals(grade)) {
                    // 添加学生和班级交联
                    StudentGardeDO studentGarde = new StudentGardeDO();
                    studentGarde.setUserId(userDTO.getId());
                    studentGarde.setGradeId(gradeDO.getId());
                    studentGarde.setId(IdGen.uuid());
                    // 添加到学生班级列表
                    studentGardeList.add(studentGarde);
                }
            };

            UserDO userDO = new UserDO();
            BeanUtils.copyProperties(userDTO, userDO);
            userList.add(userDO);

            UserRoleDO userRole = new UserRoleDO();
            userRole.setUserId(userDO.getId());
            userRole.setRoleId("3");

            userRoleList.add(userRole);
        }
        studentGardeService.saveBatch(studentGardeList);
        // 保存学生角色
        userRoleService.saveBatch(userRoleList);
        // 保存学生信息
        super.saveBatch(userList);


        return true;
    }

    /**
     * 导入教师
     * @param file
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean importTeacher(MultipartFile file) {
        // 获取学院



        Workbook workBook = MOfficeUtils.getWorkBook(file);
        Sheet sheet = workBook.getSheetAt(0);

        List<UserDO> userList = new ArrayList<>();          // 老师列表
        List<UserRoleDO> userRoleList = new ArrayList<>();  // 角色列表

        for (int i = 1; i < sheet.getLastRowNum(); i++) {
            Row row = sheet.getRow(i);
            try {
                String stringCellValue = row.getCell(0).getStringCellValue();
                if (StringUtils.isBlank(stringCellValue)) {
                    continue;
                }
            } catch (Exception e) {
                continue;
            }
            String no = row.getCell(0).getStringCellValue();                // 学号/工号
            String name = row.getCell(1).getStringCellValue();              // 姓名
            String sex = row.getCell(2).getStringCellValue();               // 性别
            String phone = row.getCell(3).getStringCellValue();             // 手机号
            String officeName = row.getCell(4).getStringCellValue();        // 学院/部门
            String pwd = row.getCell(5).getStringCellValue();        // 学院/部门
            phone = phone.trim();
            if (StringUtils.isBlank(phone)) {
                phone = null;
            }

            // 获取学院
            String officeId = null;

            // 判断是否已经存在该用户
            QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", no);
            UserDO hasUser = baseMapper.selectOne(queryWrapper);
            if (hasUser != null) {
                // 用户已经存在，跳过
                continue;
            }


            UserDTO userDTO = new UserDTO();
            userDTO.setCompanyId("1");
            userDTO.setOfficeId(officeId);
            userDTO.setName(name);
            userDTO.setUsername(no);
            userDTO.setNo(no);
            userDTO.setPhone(phone);
            // 密码默认为工号，如果有手机号码，则为手机号码后六位
            String enpwd = new Md5PasswordEncoder().encode(pwd);
            userDTO.setPassword(enpwd);
            userDTO.preInsert();


            UserDO userDO = new UserDO();
            BeanUtils.copyProperties(userDTO, userDO);
            userList.add(userDO);

            // 添加角色
            UserRoleDO userRole = new UserRoleDO();
            userRole.setUserId(userDO.getId());
            userRole.setRoleId("5");
            UserRoleDO userRole2 = new UserRoleDO();
            userRole2.setUserId(userDO.getId());
            userRole2.setRoleId("6");
            userRoleList.add(userRole);
            userRoleList.add(userRole2);


        }

        // 保存角色
        userRoleService.saveBatch(userRoleList);
        // 保存老师信息
        super.saveBatch(userList);
        return true;
    }

    public UserVO getStudentInfo(String userId) {
        return baseMapper.getStudentInfo(userId);
    }

    @Override
    public List<UserVO> serachTeacher(Wrapper<UserDO> queryWrapper) {
        return baseMapper.serachTeacher(queryWrapper);
    }

    @Override
    public List<UserVO> serachStudent(Wrapper<UserDO> queryWrapper) {
        return baseMapper.serachStudent(queryWrapper);
    }

    @Override
    public Long getStudentCount(String officeId, String enrollmentYear) {
        return baseMapper.getStudentCount(officeId, enrollmentYear);
    }

    /**
     * 登录
     * @param loginDTO
     * @return
     */
    @Override
    public UserDTO login(LoginDTO loginDTO) {
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();

        // 根据用户名查询数据库中的数据
        UserDTO userDTO = userMapper.getByUsername(username);

        // 处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (userDTO == null) {
            //账号不存在
            throw new GlobalException(GlobalExceptionEnum.ERROP_USER_PASSWORD);
        }

        // 密码比对
        // 对前端传过来的明文密码进行md5加密处理
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        if (!password.equals(userDTO.getPassword())) {     //是否匹配密码
            //密码错误
            throw new GlobalException(GlobalExceptionEnum.ERROP_PASSWORD);
        }

        // 返回实体对象
        return userDTO;
    }

    /**
     * 根据用户名查询id
     * @param username1
     * @return
     */
    @Override
    public UserDTO getIdByUsername(String username1) {
        UserDTO user = userMapper.getIdByUsername(username1);
        if (user == null) {
            // 账号不存在
            throw new GlobalException(GlobalExceptionEnum.ERROP_USER_PASSWORD);
        }
        return user;
    }
}
